/*
 * @Description: 
 * @FilePath: /STM32/USER/bsp/delay.c
 * @Author: Wei Zhou
 * @Github: https://github.com/zromyk
 * @Date: 2021-04-28 15:25:19
 * @LastEditors: Wei Zhou
 * @LastEditTime: 2021-04-28 22:03:23
 * @Copyright: Copyright 2017 muyiro. All rights reserved.
 */

#include "delay.h"

#if HARDWARE_DELAY_ENABEL 

/**
 * @brief  初始化延迟函数
 *         当使用 OS 的时候，此函数会初始化 OS 的时钟节拍
 *         SYSTICK 的时钟固定为 AHB 时钟的 1/8
 *         SYSCLK: 系统时钟频率
 * @retval None
 */
void delay_init(uint8_t SYSCLK)
{
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
    fac_us = SYSCLK / 8;              /* 不论是否使用 OS，fac_us 都需要使用 */
    fac_ms = (uint16_t)fac_us * 1000; /* 非 OS 下，代表每个 ms 需要的 systick 时钟数 */
}

/**
 * @brief  延时 us（不要大于 798915 us，最大值即 2^24/fac_us @fac_us=21)
 * @retval None
 */
void delay_us(uint32_t us)
{
    uint32_t temp;
    SysTick->LOAD = us * fac_us;              /* 时间加载 */
    SysTick->VAL = 0x00;                      /* 清空计数器 */
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* 开始倒数 */
    do
    {
        temp = SysTick->CTRL;
    } while ((temp & 0x01) && !(temp & (1 << 16))); /* 等待时间到达 */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;      /* 关闭计数器 */
    SysTick->VAL = 0X00;                            /* 清空计数器 */
}

/**
 * @brief  延时 ms （注意ms的范围）
 *          SysTick->LOAD 为 24 位寄存器，所以，最大延时为:
 *          ms <= 0xffffff*8*1000/SYSCLK
 *          SYSCLK 单位为 Hz，ms 单位为 ms
 *          对 168M 条件下，ms <= 798 ms
 * @retval None
 */
static void delay_xms(uint16_t ms)
{
    uint32_t temp;
    SysTick->LOAD = (uint32_t)ms * fac_ms;    /* 时间加载(SysTick->LOAD为24bit) */
    SysTick->VAL = 0x00;                      /* 清空计数器 */
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* 开始倒数 */
    do
    {
        temp = SysTick->CTRL;
    } while ((temp & 0x01) && !(temp & (1 << 16))); /* 等待时间到达 */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;      /* 关闭计数器 */
    SysTick->VAL = 0X00;                            /* 清空计数器 */
}

/**
 * @brief  延时 ms（0~65535）
 * @retval None
 */
void delay_ms(uint16_t ms)
{
    /* 这里用 540, 是考虑到某些客户可能超频使用， */
    /* 比如超频到 248M 的时候，delay_xms 最大只能延时 541ms 左右了 */
    uint8_t repeat = ms / 540;
    uint16_t remain = ms % 540;

    while (repeat--)
    {
        delay_xms(540);
    }
    if (remain)
    {
        delay_xms(remain);
    }
}

#else

void delay_us(uint32_t us)
{
    uint32_t t;
    
    while (us--)
    {
        t = 4;
        while(t--) {
            __nop();__nop();__nop();
            __nop();__nop();__nop();
            __nop();__nop();__nop();
            __nop();__nop();
        }
    }
}

void delay_ms(uint32_t ms)
{
    while (ms--)
    {
        delay_us(1000); 
    }
}

#endif
